package com.zhoug.zmui3.keyboard;

import android.app.Activity;
import android.graphics.Point;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.os.Build;
import android.text.Editable;
import android.text.InputType;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.EditText;
import android.widget.FrameLayout;

import com.zhoug.common3.utils.AppUtils;
import com.zhoug.common3.utils.LogUtils;
import com.zhoug.common3.utils.SoftInputMethodManager;
import com.zhoug.common3.utils.ToastUtils;
import com.zhoug.zmui3.R;

import java.lang.reflect.Method;
import java.util.Locale;

import androidx.annotation.NonNull;


/**
 * 自定义软键盘工具类
 *
 * @Author 35574
 * @Date 2021/2/1
 * @Description
 */
public class KeyboardUtils {
    private static final String TAG = ">>>KeyboardUtils";
    private static final boolean DEBUG = false;

    /***特殊键*/
    public static final int KEYCODE_SHIFT = -1;//
    public static final int KEYCODE_MODE_CHANGE = -2;
    public static final int KEYCODE_CANCEL = -3;////关闭
    public static final int KEYCODE_DONE = -4;//确定
    public static final int KEYCODE_DELETE = -5;
    public static final int KEYCODE_ALT = -6;
    public static final int KEYCODE_SKIP = -7;//不需要输入任何字符
    public static final int KEYCODE_UPPER_CASE = -8;//大写字母键盘
    public static final int KEYCODE_LOWER_CASE = -9;//小写字母键盘
    public static final int KEYCODE_TYPE_ABC = -10;//软键盘切换键字母
    public static final int KEYCODE_TYPE_123 = -11;//软键盘切换键数字
    public static final int KEYCODE_TYPE_CHARACTER = -12;////软键盘切换键符号


    public static final class KeyboardType {
        public static final int NUMBER = 1;//数字键盘
        public static final int LETTER_NUMBER = 2;//字母数字键盘
        public static final int LETTER = 3;//字母键盘
        public static final int CHARACTER = 4;//字符键盘

    }


    private static final int ANIM_DURATION = 200;
    private EditText[] mEditTexts;
    private EditText mEditText;//输入框
    private KeyboardView mKeyboardView;//软键盘的渲染显示容器
    private Keyboard mKeyboardUpper;//自定义的软键盘:大写
    private Keyboard mKeyboardLower;//自定义的软键盘:小写
    private Keyboard mKeyboardNumber;//自定义的软键盘:数字
    private Keyboard mKeyboardSymbol;//自定义的软键盘:符号
    private Keyboard mKeyboardLast;//上次的软键盘
    private Activity mActivity;
    private int mDefScrollY = Integer.MAX_VALUE;//editText最开始的滚动偏移量
    private boolean autoAdd;


    /**
     * EditText焦点改变监听
     */
    private View.OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (DEBUG) {
                LogUtils.d(TAG, "onFocusChange:" + v + ":" + hasFocus);
            }
            boolean f = false;
            if (mEditTexts != null && mEditTexts.length > 0) {
                for (EditText editText : mEditTexts) {
                    if (editText.hasFocus()) {
                        mEditText = editText;
                        f = true;
                        break;
                    }
                }

            }
            if (f) {
                showSoftKeyboard();
            } else {
                hideSoftKeyboard();
            }
        }
    };

    /**
     * 软键盘监听
     */
    private KeyboardView.OnKeyboardActionListener onKeyboardActionListener = new KeyboardView.OnKeyboardActionListener() {
        @Override
        public void onPress(int primaryCode) {

        }

        @Override
        public void onRelease(int primaryCode) {

        }

        @Override
        public void onKey(int primaryCode, int[] keyCodes) {
            if (mEditText == null) return;
            Editable text = mEditText.getText();
            int start = mEditText.getSelectionStart();
            if (primaryCode == KEYCODE_DELETE) {
                int length = text.length();
                if (length > 0 && start > 0) {
                    text.delete(start - 1, start);
                    if (DEBUG) {
                        LogUtils.d(TAG, "onKey:删除");
                    }
                }
            } else if (primaryCode == KEYCODE_UPPER_CASE) {
                changeKeyboard(mKeyboardUpper, KeyboardType.LETTER_NUMBER);

            } else if (primaryCode == KEYCODE_LOWER_CASE) {
                changeKeyboard(mKeyboardLower, KeyboardType.LETTER_NUMBER);
                translationParent();

            } else if (primaryCode == KEYCODE_TYPE_123) {
                changeKeyboard(mKeyboardNumber, KeyboardType.NUMBER);

            } else if (primaryCode == KEYCODE_TYPE_ABC) {
                changeKeyboard(mKeyboardLower, KeyboardType.LETTER_NUMBER);

            } else if (primaryCode == KEYCODE_TYPE_CHARACTER) {
                changeKeyboard(mKeyboardSymbol, KeyboardType.CHARACTER);

            } else if (primaryCode == KEYCODE_DONE) {
                hideSoftKeyboard();
            } else if (primaryCode == KEYCODE_SKIP) {
//                toast("跳过输入");

            } else {
                text.insert(start, Character.toString((char) primaryCode));
            }
        }

        @Override
        public void onText(CharSequence text) {

        }

        @Override
        public void swipeLeft() {

        }

        @Override
        public void swipeRight() {

        }

        @Override
        public void swipeDown() {

        }

        @Override
        public void swipeUp() {

        }
    };

    private View.OnClickListener editOnclick = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (v.hasFocus()) {
                showSoftKeyboard();
            }
        }
    };

    private void changeKeyboard(Keyboard keyboard, int keyboardType) {
        setKeyboard(keyboard, keyboardType);
        translationParent();
    }

    private void setKeyboard(Keyboard keyboard, int keyboardType) {
        mKeyboardView.setKeyboard(keyboard);
        if (mKeyboardView instanceof ZMUIKeyboardView) {
            ((ZMUIKeyboardView) mKeyboardView).setKeyboardType(keyboardType);
        }
    }

    public KeyboardUtils(@NonNull Activity activity, @NonNull KeyboardView keyboardView) {
        autoAdd = false;
        mActivity = activity;
        mKeyboardView = keyboardView;
        mKeyboardLower = new Keyboard(mActivity, R.xml.zmui_lower_letter_number_key_board);
        mKeyboardUpper = new Keyboard(mActivity, R.xml.zmui_upper_letter_number_key_board);
        mKeyboardNumber = new Keyboard(mActivity, R.xml.zmui_number_key_board);
        mKeyboardSymbol = new Keyboard(mActivity, R.xml.zmui_symbol_key_board);
        setKeyboard(mKeyboardLower, KeyboardType.LETTER_NUMBER);
        mKeyboardView.setEnabled(true);
        mKeyboardView.setPreviewEnabled(false);
        mKeyboardView.setOnKeyboardActionListener(onKeyboardActionListener);
    }

    public KeyboardUtils(@NonNull Activity activity) {
        mActivity = activity;
        autoAdd = true;
        mKeyboardView = (KeyboardView) LayoutInflater.from(activity).inflate(R.layout.zmui_keyboardview_layout, null);
        mKeyboardView.setVisibility(View.VISIBLE);
        mKeyboardLower = new Keyboard(mActivity, R.xml.zmui_lower_letter_number_key_board);
        mKeyboardUpper = new Keyboard(mActivity, R.xml.zmui_upper_letter_number_key_board);
        mKeyboardNumber = new Keyboard(mActivity, R.xml.zmui_number_key_board);
        mKeyboardSymbol = new Keyboard(mActivity, R.xml.zmui_symbol_key_board);
        setKeyboard(mKeyboardLower, KeyboardType.LETTER_NUMBER);
        mKeyboardView.setEnabled(true);
        mKeyboardView.setPreviewEnabled(false);
        mKeyboardView.setOnKeyboardActionListener(onKeyboardActionListener);
    }


    public void attachTo(EditText... editTexts) {
        this.mEditTexts = editTexts;
        if (editTexts != null && editTexts.length > 0) {
            for (EditText editText : editTexts) {
                editText.setOnFocusChangeListener(onFocusChangeListener);
                editText.setOnClickListener(editOnclick);
                hideSystemSoftKeyboard(editText);
            }
        }

    }


    /**
     * 软键盘是否显示
     *
     * @return
     */
    public boolean isShowing() {
        if (autoAdd) {
            return mKeyboardView != null && mKeyboardView.getParent() != null;
        }
        return mKeyboardView != null && mKeyboardView.getVisibility() == View.VISIBLE;
    }


    /**
     * 显示软键盘
     */
    private void showSoftKeyboard() {
        if (isShowing()) {
            translationParent();
            return;
        }
        //隐藏系统软键盘
        SoftInputMethodManager softInputMethodManager = new SoftInputMethodManager(mActivity);
        softInputMethodManager.hideSoftInput(mActivity);
        //显示软键盘
        if (autoAdd) {
            ViewGroup decorView = (ViewGroup) mActivity.getWindow().getDecorView();
            FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
            layoutParams.gravity = Gravity.BOTTOM;
            decorView.addView(mKeyboardView, layoutParams);

        } else {
            mKeyboardView.setVisibility(View.VISIBLE);
        }
        Animation animation = AnimationUtils.loadAnimation(mKeyboardView.getContext(), R.anim.zmui_in_bottom);
        animation.setDuration(ANIM_DURATION);
        mKeyboardView.setAnimation(animation);

        translationParent();
    }

    /**
     * 计算是否需要移动布局
     */
    private void translationParent() {
//        ViewGroup parent = (ViewGroup) mEditText.getParent();
        ViewGroup parent = (ViewGroup) mActivity.getWindow().getDecorView();
        if (mDefScrollY == Integer.MAX_VALUE) {
            mDefScrollY = parent.getScrollY();
        }
        int[] location = new int[2];
        mEditText.getLocationInWindow(location);
        int editHeight = mEditText.getHeight();
        int bottom = location[1] + editHeight;
        int statusHeight = AppUtils.getStatusHeight();
        Point screenSize = AppUtils.getScreenSize();
        AppUtils.measureView(mKeyboardView);

        int keyboardViewHeight = mKeyboardView.getMeasuredHeight();
        int freeBottom = screenSize.y + statusHeight - bottom;
        //计算底部的剩余空间,不足以显示软键盘则向上移动布局
        int dis = keyboardViewHeight - freeBottom;
        int scrollY = 0;
        if (DEBUG) {
            LogUtils.d(TAG, "trans:dis=" + dis);
        }
        if (dis > 0) {
            scrollY = dis;
            parent.scrollBy(0, scrollY);
        } else if (dis < 0) {
            //底部控件有余,判断是否需要回滚
            int curScrollY = parent.getScrollY();
            if (DEBUG) {
                LogUtils.d(TAG, "translationParent:curScrollY=" + curScrollY);
            }
            if (curScrollY != mDefScrollY) {
                scrollY = Math.max(dis, mDefScrollY - curScrollY);
                parent.scrollBy(0, scrollY);
            }

        }
        if (DEBUG) {
            LogUtils.d(TAG, String.format(Locale.CANADA, "trans:bottom=%d,editHeight=%d,keyboardViewHeight=%d,scrollY=%d,mDefScrollY=%d",
                    bottom, editHeight, keyboardViewHeight, scrollY, mDefScrollY));
        }
    }


    /**
     * 隐藏软键盘
     */
    public void hideSoftKeyboard() {
        if (isShowing()) {
            Animation animation = AnimationUtils.loadAnimation(mKeyboardView.getContext(), R.anim.zmui_out_bottom);
            animation.setDuration(ANIM_DURATION);
            mKeyboardView.setAnimation(animation);
            if (autoAdd) {
                ViewGroup parent = (ViewGroup) mKeyboardView.getParent();
                parent.removeView(mKeyboardView);
            } else {
                mKeyboardView.setVisibility(View.GONE);
            }
            if (mDefScrollY != Integer.MAX_VALUE) {
//                ViewGroup parent = (ViewGroup) mEditText.getParent();
//                parent.scrollTo(0, mDefScrollY);
                ViewGroup parent = (ViewGroup) mActivity.getWindow().getDecorView();
                parent.scrollTo(0, mDefScrollY);

            }

        }
    }

    /**
     * 阻止EditText获取焦点时弹出系统软键盘
     */
    public static void hideSystemSoftKeyboard(EditText editText) {
        int sdkInt = Build.VERSION.SDK_INT;
        if (sdkInt >= 11) {
            try {
                Class<EditText> cls = EditText.class;
                Method setShowSoftInputOnFocus;
                setShowSoftInputOnFocus = cls.getMethod("setShowSoftInputOnFocus", boolean.class);
                setShowSoftInputOnFocus.setAccessible(true);
                setShowSoftInputOnFocus.invoke(editText, false);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            editText.setInputType(InputType.TYPE_NULL);
        }
    }

    private void toast(String msg) {
        ToastUtils.toastShort(msg);
    }

    /**
     * 禁止截屏
     */
    public  void noScreenShort(){
        mActivity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
                WindowManager.LayoutParams.FLAG_SECURE);
    }
}
